home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / A3DEV.ZIP / DEVELOP.TXT < prev    next >
Encoding:
Text File  |  1996-11-12  |  22.0 KB  |  698 lines

  1.  
  2. *-------------------------------------------------------*
  3. * AFD concept overview:                    *
  4. *-------------------------------------------------------*
  5.  
  6. The AFD system simply allows Apex to read & write image
  7. file formats using external file support modules. These
  8. modules can be recognised by their file extension *.AFD.
  9. You will find some commonly used formats supplied in this
  10. form alongside Apex Alpha itself.
  11.  
  12. One benefit of this system is to allow users/developers
  13. to produce their own AFD support modules where necessary,
  14. providing that development details are freely available.
  15. Fortunately, the AFD format is described here in great
  16. detail, in the hope that users will release a multitude
  17. of new drivers for the program. That's the idea anyway.
  18.  
  19. *-------------------------------------------------------*
  20. * AFD implementation:                    *
  21. *-------------------------------------------------------*
  22.  
  23. The AFD file format consists of a small (executable)
  24. program which Apex will automatically load from the
  25. default AFD path into memory and immediately execute as
  26. if it were a normal TOS program.
  27.  
  28. *-------------------------------------------------------*
  29.  
  30. 1) First call to module / initialisation.
  31.  
  32. At this point, the AFD module should make any special
  33. initialisation calls required to set up internal global
  34. structures, global variables or even data buffers in
  35. extreme cases.
  36.  
  37. The AFD program should at this point also fill out the
  38. relevant function pointers & format specific variables
  39. of the global afd_structure, which are used for future
  40. calls made to the AFD from Apex itself.
  41.  
  42. The initialisation call to the AFD module takes place in
  43. the USER mode processor state (normal operating mode),
  44. and will only ever happen once. The initialisation part
  45. of the module can be written in the form of a simple
  46. function or subroutine, or as a fully implemented Pterm /
  47. Pterm0 terminated program. Both systems are handled for
  48. the benefit of C-compiled modules which can prove
  49. difficult when attempting to generate raw (but still
  50. relocatable) external function-based modules like these.
  51.  
  52. *-------------------------------------------------------*
  53.  
  54. 2) Function calls to module.
  55.  
  56. All future calls to the AFD module will be made via the
  57. afd_structure, which should now contain pointers to the
  58. appropriate 'examine', 'decoder' & 'encoder' functions
  59. after the initialisation call described previously. These
  60. function calls will always be made in SUPERVISOR mode
  61. processing state (i.e. protected mode) and will ALWAYS
  62. be treated as normal functions or subroutines.
  63.  
  64. *-------------------------------------------------------*
  65. * AFD rules & Apex compatibility issues:        *
  66. *-------------------------------------------------------*
  67.  
  68. There are a few rules and some limitations imposed on the
  69. AFD module's actions & capabilities, but the restrictions
  70. are far less severe than you might expect. We have gone
  71. to great lengths to make life as easy as possible for the
  72. prospective AFD developer.
  73.  
  74. The most important rules are specified here, in outline
  75. form - partly to help the developer avoid pitfalls and
  76. partly to show how Apex interfaces with the module. It
  77. is wise to skim this section at the very least, if not
  78. absorb it in detail.
  79.  
  80. *-------------------------------------------------------*
  81.  
  82. 1) Programming considerations:
  83.  
  84. The program code does NOT have to be position independent,
  85. although it CAN be if this is required by the programmer.
  86.  
  87. Apex expects a fully relocatable GEMDOS executable, where
  88. the first piece of executable code encountered is the
  89. initialisation routine. In the case of 'C', this will be
  90. standard startup code, including a call to function 'main',
  91. and terminated with a 'Pterm' call. In the case of ASM
  92. however, this will just be a simple module initialisation
  93. subroutine, terminated with an 'rts' instruction.
  94.  
  95. *-------------------------------------------------------*
  96.  
  97. 2) Memory initialisation:
  98.  
  99. The TOS 'Mshrink' call IS available for compatibility
  100. reasons, but it does absolutely nothing.
  101.  
  102. Apex will automatically calculate how much space is used
  103. by the module's TEXT, DATA & BSS sections and reserve the
  104. correct amount, which makes Mshrink redundant in most
  105. situations - including 'C' startup code.
  106.  
  107. The module will have exactly 4096 bytes of additional TPA
  108. space (i.e. un-shrunk memory) available on execution for
  109. the stack, which although useless for ASM developers, is
  110. necessary in the case of C startup code, which will most
  111. often attempt to place the stack pointer at the very end
  112. of the TPA. 4kB should be enough for any file encoding /
  113. decoding function to operate perfectly.
  114.  
  115. *-------------------------------------------------------*
  116.  
  117. 3) Memory allocation/deallocation:
  118.  
  119. The TOS 'Malloc', 'MXalloc' & 'Mfree' calls are always
  120. available, but they have been routed through the internal
  121. Apex memory manager. Although radically different from
  122. the TOS allocation system, the internal functions emulate
  123. the standard calls perfectly, except in the case of
  124. Mshrink, which disabled, and is of no consequence here.
  125.  
  126. There is effectively no limit placed on the number of
  127. Malloc calls which can be made inside the module, and
  128. defragmentation is not much of a problem either. Apex
  129. handles this much better than the standard TOS memory
  130. pool. It is however wise to be careful with allocation
  131. order and block size, as there's no point in trying to
  132. make life difficult for Apex for no good reason.
  133.  
  134. Memory blocks can be left behind as permanent storage,
  135. and they will not be freed unless the special 'salloc'
  136. call has been used in place of malloc (which stacks the
  137. block handles and releases all un-freed blocks on module
  138. termination - for lazy people!) when the module returns
  139. control to Apex. This may be necessary in some cases, but
  140. is not good practice and should be avoided wherever
  141. possible.
  142.  
  143. No harm will come to any blocks deliberately left behind
  144. by the module if the programmer needs to do this. 'C'
  145. programs will often leave structures behind permanently,
  146. depending on what is going on in the code.
  147.  
  148. *-------------------------------------------------------*
  149.  
  150. 4) File activity:
  151.  
  152. The standard Fopen / Fclose / Fread / Fwrite etc. calls
  153. are of course available for ease of use and compatibility
  154. reasons, but it is better to use the internal Apex file
  155. support functions because Apex then has the ability to
  156. report errors properly via internal dialog boxes.
  157.  
  158. Do not leave the AFD module without closing all of your
  159. files. Apex does not do this for you.
  160.  
  161. *-------------------------------------------------------*
  162.  
  163. 5) Module termination (memory):
  164.  
  165. Do NOT rely on the standard TOS 'Pterm' or 'Pterm0' 
  166. termination calls to release ANY remaining memory blocks
  167. after the module is finished doing it's job. This means
  168. during the initialisation call specifically, since the
  169. function calls should not be terminated in this way
  170. under any circumstances.
  171.  
  172. Any calls made to the STANDARD malloc functions (esp. in
  173. the case of 'C' based module development) will REMAIN
  174. allocated until Apex ITSELF terminates, unless the module
  175. cleans up after itself - which is a good idea if you want
  176. to avoid 'runaway' memory leakage problems.
  177.  
  178. *-------------------------------------------------------*
  179.  
  180. 6) Termination rules:
  181.  
  182. Don't terminate the module with a 'Ptermres' - that's
  183. just plain silly!
  184.  
  185. All calls which complete without errors should return
  186. a value of zero (0L) either as a function return value
  187. (for 'C') or in register 'D0' (for ASM). Any calls which
  188. fail or encounter a fatal error should return -1 instead,
  189. so Apex can deal with the consequences. Failure to adhere
  190. to these return codes can lead to dangerous AFD files.
  191.  
  192. *-------------------------------------------------------*
  193. * Apex -> AFD module calling details:            *
  194. *-------------------------------------------------------*
  195.  
  196. 1) The initialisation function (function 'main').
  197.  
  198. The first thing the module should do (main function in
  199. 'C', or equivalent subroutine in ASM) is find the global
  200. Apex communication structure, which is officially called
  201. afd_structure in the examples. After finding the address
  202. of this structure, it should be filled out with module
  203. specific details including function pointers and serial
  204. numbers. There are several very useful function pointers
  205. already present in the structure for the benefit of the
  206. module itself, covering file read/write and memory
  207. allocation calls. These are optional, and it may be useful
  208. to read these function addresses into global function
  209. pointers for later use.
  210.  
  211. What follows is a simple example covering a bare minimum
  212. implementation of the AFD initialisation sequence.
  213.  
  214. An assembly programmer would something like this...
  215.  
  216. ; Get AFD structure base address.
  217.     
  218. main:    move.w        #2001,-(sp)
  219.     trap        #14
  220.     addq.l        #2,sp
  221.     move.l        d0,afd_structure_ptr
  222.     move.l        d0,a0
  223.  
  224. ; Place file extension string pointer in AFD structure.
  225.  
  226.     move.l        #extension_string,afd_extension(a0)
  227.  
  228. ; Fill out AFD structure with function pointers.
  229.  
  230.     move.l        #inquire_routine,afd_inquire(a0)
  231.     move.l        #decoder_routine,afd_decode(a0)
  232.     move.l        #encoder_routine,afd_encode(a0)
  233.  
  234. ; Choose a 16-bit colour for displaying format inside Apex.
  235.  
  236.     move.w        #highlight_colour,afd_colour(a0)
  237.  
  238. ; Choose a (hopefully) unique file format identifier.
  239.  
  240.     move.w        #serial,afd_id(a0)
  241.  
  242. ; Make copies of all available Apex function pointers,
  243. ; because it's much easer to call them 'indirect absolute'
  244. ; using 'jsr ([function_ptr.l])' than it is to call them
  245. ; straight from the structure!
  246.  
  247.     move.l        afd_malloc(a0),malloc_ptr
  248.     move.l        afd_dealloc(a0),dealloc_ptr
  249.     move.l        afd_salloc(a0),salloc_ptr
  250.     move.l        afd_thread(a0),thread_ptr
  251.     move.l        afd_open(a0),open_ptr
  252.     move.l        afd_close(a0),close_ptr
  253.     move.l        afd_create(a0),create_ptr
  254.     move.l        afd_read(a0),read_ptr
  255.     move.l        afd_write(a0),write_ptr
  256.     move.l        afd_seek(a0),seek_ptr
  257.     move.l        afd_examine(a0),examine_ptr
  258.     move.l        afd_patch(a0),patch_ptr
  259.  
  260. ; Return control to Apex
  261.  
  262.     rts
  263.         
  264. Where a 'C' developer would use something like this...
  265.  
  266. char *extension = "tga";   /* file extension string */
  267.  
  268. long main()
  269. {
  270.    struct alpha *alpha_ptr;
  271.  
  272. /* Get AFD structure base address */
  273.  
  274.    alpha_ptr = Alphabase();
  275.  
  276. /* Place file extension string pointer in AFD structure */
  277.  
  278.    alpha_ptr -> afd_extension = extension_string;
  279.  
  280. /* Fill out AFD structure with function pointers */
  281.  
  282.    alpha_ptr -> afd_inquire = &inquire_function;
  283.    alpha_ptr -> afd_decode = &decode_function;
  284.    alpha_ptr -> afd_encode = &encode_function;
  285.  
  286. /* Choose a 16-bit colour for displaying format inside Apex */
  287.  
  288.    alpha_ptr -> afd_colour = 0x1234;
  289.  
  290. /* Choose a (hopefully) unique file format identifier */
  291.  
  292.    alpha_ptr -> afd_id = serial;
  293.    
  294.    return 0L;
  295. };
  296.  
  297. Note: Header files are supplied for 'C' and ASM programmers
  298. to make these calls & access the AFD structures shown in
  299. these examples.
  300.  
  301. *-------------------------------------------------------*
  302.  
  303. 2) The image 'inquire' function:
  304.  
  305. This function simply examines the header of the file
  306. indicated in the filename buffer 'adf_filename' and if the
  307. file is valid, returns the width & height in the adf_width
  308. & adf_height structure fields. If the file is invalid,
  309. then the adf_width & adf_height fields should be zero, and
  310. a -1L return code passed instead of 0L.
  311.  
  312. Here is an example of a basic image-inquire function.
  313.  
  314.  
  315. Assembly language example:
  316.  
  317.  
  318. inquire_function:
  319.  
  320. ; Open the file for read-only access
  321.  
  322.     move.w        #none,file_handle
  323.     move.l        struct_ptr,a6
  324.     lea        afd_filename(a6),a0
  325.     moveq        #0,d0
  326.     jsr        ([open_ptr.l])
  327.     tst.l        d0
  328.     bmi.s        .error
  329.     move.w        d0,file_handle
  330.  
  331. ; Read the file header
  332.  
  333.     moveq        #our_header_size,d1
  334.     move.l        struct_ptr,a6
  335.     lea        afd_gpbuffer(a6),a0
  336.     jsr        ([read_ptr.l])
  337.     tst.l        d0
  338.     bmi.s        .error
  339.  
  340. ; Update the adf_structure to reflect the image size
  341.  
  342.     move.l        struct_ptr,a6
  343.     lea        afd_gpbuffer(a6),a0
  344.     move.w        our_image_width(a0),d1
  345.     move.w        our_image_height(a0),d2
  346.     cmp.w        #5120,d1 ; rudimentary validation
  347.     bhi.s        .error
  348.     cmp.w        #5120,d2 ; rudimentary validation
  349.     bhi.s        .error
  350.     move.l        struct_ptr,a6
  351.     move.w        d1,afd_width(a6)
  352.     move.w        d2,afd_height(a6)
  353.  
  354. ; Return control to Apex - '0' return code for success.
  355.  
  356. .done:    moveq        #0,d0
  357.     bra.s        .exit
  358.  
  359. ; Return control to Apex - '-1' return code for error.
  360.  
  361. .error:    move.l        struct_ptr,a6
  362.     clr.w        afd_width(a6)
  363.     clr.w        afd_height(a6)
  364.     moveq        #-1,d0
  365.  
  366. ; Close file and return. '-1' file handles are ignored.
  367.  
  368. .exit:    move.l        d0,-(sp)
  369.     move.w        file_handle,d0
  370.     jsr        ([close_ptr.l])
  371.     move.l        (sp)+,d0
  372.     rts
  373.  
  374.  
  375. A simple 'C' implementation:
  376.  
  377. long inquire_function()
  378. {
  379.  
  380.    long exitcode;
  381.    struct alpha *alpha_ptr;
  382.  
  383. /* this is just an imaginary structure for the file reader */
  384.  
  385.    struct imagestuff *image_info;
  386.  
  387. /* Get AFD structure base address */
  388.  
  389.    alpha_ptr = Alphabase();
  390.  
  391. /* Examine the file, reading header into a suitable structure */
  392. /* 'adf_filename' is the 1k filename BUFFER - it's NOT a pointer! */
  393.  
  394.    exitcode = examine_image(&(alpha_ptr -> afd_filename),image_info)
  395.  
  396. /* Only update afd_structure if the file was valid */
  397.  
  398.    if !(exitcode)
  399.    {
  400.       alpha_ptr -> afd_width = image_info -> image_width;
  401.       alpha_ptr -> afd_height = image_info -> image_height;
  402.    }
  403.  
  404. /* Return control to Apex */
  405.  
  406.    return exitcode;
  407.    
  408. }
  409.  
  410. *-------------------------------------------------------*
  411.  
  412. 3) The image 'decoder' function:
  413.  
  414. This function should take the same shape as the inquire
  415. function, but should concentrate on decoding the image
  416. data into the space located by the pointer 'adf_imageptr'.
  417.  
  418. Again, the filename is passed in the 1k buffer called
  419. 'adf_filename'. A general purpose 1k buffer is also
  420. provided for convenience.
  421.  
  422. DO NOT change the afd_width & afd_height fields in the
  423. afd_structure, as these are required by Apex for other
  424. purposes not covered here. The correct amount of space
  425. will be allocated before the decoder function is called,
  426. based on the width & height previously returned by the
  427. inquire function.
  428.  
  429. The format into which the image should be decoded is
  430. as follows:
  431.  
  432. Each pixel consists of 4 bytes. RED, GREEN, BLUE and
  433. ALPHA. All colour channels are zero before the decoder is
  434. called, so it's not necessary to fill out the ALPHA
  435. channel if it is not available.
  436.  
  437. Pixel format: $RR,$GG,$BB,$AA
  438.  
  439. The image buffer will simply be (width * height * 4) bytes 
  440. in size. No dithering or colour reduction is required.
  441.  
  442. *-------------------------------------------------------*
  443.  
  444. 4) The image 'encoder' function:
  445.  
  446. Same as decoder, but works in the other direction.
  447.  
  448. <unfinished>
  449.  
  450. *-------------------------------------------------------*
  451. *    Detailed description of 'afd_structure'        *
  452. *-------------------------------------------------------*
  453.  
  454. afd_malloc        /* Apex Malloc routine (in) */
  455.  
  456.  This points to the internal Apex malloc function. The
  457.  parameters & return codes are the same as TOS malloc,
  458.  except for the fact that -1L can be returned on an error
  459.  instead of the usual 0L.
  460.  
  461.  d0.l = block size, or -1 for largest block.
  462.  d1.l = memory type (0->3 as with TOS Mxalloc)
  463.  
  464.  Returns -1L on error, or size of largest block.
  465.  
  466. *-------------------------------------------------------*
  467.  
  468. afd_dealloc        /* Apex Mfree routine (in) */
  469.  
  470.  This is the matching Apex mfree function. It will
  471.  deallocate blocks allocated with either adf_malloc or
  472.  adf_salloc. Parameters & codes match that of TOS.
  473.  
  474.  d0.l = block address (handle) to deallocate.
  475.  
  476.  Returns -1L on error.
  477.  
  478. *-------------------------------------------------------*
  479.  
  480. afd_salloc        /* Apex stacked malloc routine */
  481.  
  482.  This is identical to the afd_malloc routine, except
  483.  it records all block handles successfully allocated so
  484.  they may be automatically freed by Apex when the module
  485.  returns control. It is a dirty practice, but it can
  486.  make life easier for some. It can also cut down the
  487.  size and complexity of otherwise simple ASM modules
  488.  due to reduced error handling requirements. Avoid using
  489.  this for large operations, as it is not an efficent 
  490.  way to handle your resources.
  491.  
  492. *-------------------------------------------------------*
  493.  
  494. afd_thread        /* Apex background thread (in) */
  495.  
  496.  Callback function. Call this every so often to update
  497.  the very low-priority background jobs taking place inside
  498.  the main Apex core. Things like memory indicators can
  499.  be refreshed with this call.
  500.  
  501. *-------------------------------------------------------*
  502.  
  503. afd_open        /* Fopen (in) */
  504.  
  505.  Same as TOS Fopen file function.
  506.  
  507.  a0.l = filename
  508.  d0.w = mode
  509.  
  510.  Return parameters & codes match those of TOS.
  511.  
  512. *-------------------------------------------------------*
  513.  
  514. afd_close        /* Fclose (in) */
  515.  
  516.  Same as TOS Fclose function. Returns -1 on error
  517.  and ignores -1 handles, to make life a little easier
  518.  for programmers who use the -1 code for 'unopened'
  519.  file status on global file handles.
  520.  
  521.  d0.w = handle
  522.  
  523.  Returns -1L on error, otherwise matches TOS return
  524.  codes.
  525.  
  526. *-------------------------------------------------------*
  527.  
  528. afd_create        /* Fcreate (in) */
  529.  
  530.  a0.l = filename
  531.  
  532.  Same as TOS Fcreate function.
  533.  
  534.  Return codes match those of TOS.
  535.  
  536. *-------------------------------------------------------*
  537.  
  538. afd_read        /* Fread (in) */
  539.  
  540. Same as TOS Fread, except it will return an error for
  541. 'truncated' reads. TOS compatible return codes are
  542. always returned in d1 if they are required.
  543.  
  544.  d0.w = handle
  545.  d1.l = size
  546.  a0.l = buffer
  547.  
  548.  Returns -1L in d0 on a truncated read.
  549.  Returns TOS error codes in d1 - and also in d0 when read
  550.  is not truncated.
  551.  
  552. *-------------------------------------------------------*
  553.  
  554. afd_write        /* Fwrite (in) */
  555.  
  556. Same as afd_read, but for writing. Same codes and
  557. parameters are used as with afd_read.
  558.  
  559. *-------------------------------------------------------*
  560.  
  561. afd_seek        /* Fseek (in) */
  562.  
  563. Same as TOS Fseek.
  564.  
  565.  d0.w = handle
  566.  d1.w = mode
  567.  d2.l = size
  568.  
  569.  Return codes match those of TOS.
  570.  
  571. *-------------------------------------------------------*
  572.  
  573. afd_examine        /* Fseek + Fread (in) */
  574.  
  575.  Combined seek & read operation. Ideal for examining
  576.  simple file headers etc.
  577.  
  578.  d0.w = handle
  579.  d1.l = size
  580.  d2.l = index
  581.  a0.l = buffer
  582.  
  583.  Returns -1L on seek error, but otherwise matches TOS
  584.  Fread return codes.
  585.  
  586. *-------------------------------------------------------*
  587.  
  588. afd_patch        /* Fseek + Fwrite (in) */
  589.  
  590.  Combined seek & write operation. Ideal for updating
  591.  simple file headers etc.
  592.  
  593.  Parameters & codes match those of 'afd_examine', with
  594.  Fwrite return codes.
  595.  
  596. *-------------------------------------------------------*
  597.  
  598. afd_extension        /* pointer to format extension string (out) */
  599.  
  600.  This is a longword pointer to a short zero-terminated string
  601.  containing the ascii file extension of the format supported
  602.  by the AFD module. This field MUST be updated by the module
  603.  during it's initialisation call. The string buffer should
  604.  be supplied by the module itself.
  605.  
  606. *-------------------------------------------------------*
  607.  
  608. afd_inquire        /* format inquire routine address (out) */
  609.  
  610.  This is the function pointer for the routine which Apex
  611.  calls to examine any files encountered with the file
  612.  extension indicated by 'afd_extension' (above). This
  613.  field MUST be updated during the module initialisation
  614.  stage. This function should update the afd_width &
  615.  afd_height fields of the afd_structure if the file is
  616.  valid, and return a 0L code for success, or -1L for a
  617.  fatal error.
  618.  
  619. *-------------------------------------------------------*
  620.  
  621. afd_decode        /* format decoder routine address (out) */
  622.  
  623.  This function decodes the image into a buffer (created
  624.  by Apex using the afd_width & afd_height fields updated
  625.  earlier with afd_inquire). The buffer can be found using
  626.  the afd_imageptr field, which should only ever be read,
  627.  and never be modified directly by the driver. The routine
  628.  should return 0L for success, or -1L for a fatal error.
  629.  
  630. *-------------------------------------------------------*
  631.  
  632. afd_encode        /* format encoder routine address (out) */
  633.  
  634.  Identical to afd_decode, but for saving files instead
  635.  of loading them.
  636.  
  637. *-------------------------------------------------------*
  638.  
  639. afd_colour        /* format highlight colour (out) */
  640.  
  641.  A colour encoded in %RRRRRGGGGGGBBBBB format which is
  642.  used to represent the file format inside Apex itself.
  643.  
  644. *-------------------------------------------------------*
  645.  
  646. afd_id            /* format id (out) */
  647.  
  648.  A unique serial number used to differentiate between file
  649.  formats with the same file extension, but different
  650.  encode/decode AFD modules. Although it is not yet supported,
  651.  it is wise to fill the value with something meaningful
  652.  to avoid future conflicts.
  653.  
  654. *-------------------------------------------------------*
  655.  
  656. afd_width        /* image width (in/out) */
  657. afd_height        /* image height (in/out) */
  658.  
  659.  These should only ever be modified by the afd_inquire
  660.  routine, but can be read by the afd_decode & afd_encode
  661.  functions to work out image dimensions.
  662.  
  663. *-------------------------------------------------------*
  664.  
  665. afd_imageptr        /* 32bit imagebuffer pointer (in) */
  666.  
  667.  This should never be modified, and points to the x * y * 4
  668.  byte buffer into which the image should be decoded, or
  669.  from which the image should be saved.
  670.  
  671. *-------------------------------------------------------*
  672.  
  673. afd_filesize        /* file size in bytes (in) */
  674.  
  675.  This holds the size of the file in question. Do not
  676.  modify.
  677.  
  678. *-------------------------------------------------------*
  679.  
  680. afd_filename        /* 1k filename string buffer (in) */
  681.  
  682.  This is a 1024 byte buffer (not a pointer) which contains
  683.  the full path and filename of the file to be examined,
  684.  loaded or written to disk. It is always zero terminated.
  685.  Do not modify.
  686.  
  687. *-------------------------------------------------------*
  688.  
  689. afd_gpbuffer        /* 1k general purpose buffer (in) */
  690.  
  691.  This is a 1024 byte general purpose buffer which can be
  692.  useful for temporary work, and for reading file headers
  693.  for examination. It will be trashed when the module
  694.  returns control to Apex, so don't leave any important
  695.  data behind that you might want back!
  696.  
  697. *-------------------------------------------------------*
  698.